﻿// Original author contact info: Owen Emlen (owene_1998@yahoo.com)
// Note: other individuals may also have contributed to this code
// Project hosted on CodePlex.com as of 1/10/2009 at http://wpfimageviewer.codeplex.com
using System;
using System.Linq.Expressions;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using BrainTechLLC;
using System.Windows.Threading;
using System.Windows;
using BrainTechLLC.ThreadSafeObjects;
using System.Threading;
using System.Diagnostics;
using System.Reflection;
using System.Globalization;
using System.Runtime.Serialization;
using System.Dynamic;
using Expression = System.Linq.Expressions.Expression;

namespace BrainTechLLC.WPF
{
    [Serializable]
    [DataContract]
    public partial class MultiViewModelBase : BaseNotifyPropertyChangedUI, IDynamicMetaObjectProvider
    {
        protected List<object> _Object = new List<object>();

        public List<object> Object
        {
            get { return _Object; }
        }

        #region IDynamicMetaObjectProvider Members

        public DynamicMetaObject GetMetaObject(System.Linq.Expressions.Expression parameter)
        {
            return new CustomMetaObject(parameter, this);
        }

        #endregion

        public virtual void OnItemRaisedPropertyChanged(string propertyName)
        {
        }

        public object GetValue(object o, string propertyName)
        {
            object value;
            MultiViewModelBase vm = o as MultiViewModelBase;
            Type t = o.GetType();
            PropertyInfo pi = t.GetProperty(propertyName);
            if (pi == null)
            {
                object objectFound = null;
                for (int n = 0; n < vm.Object.Count; n++)
                {
                    var obj = vm.Object[n];
                    if (obj == null)
                        continue;

                    t = obj.GetType();
                    pi = t.GetProperty(propertyName);

                    if (pi != null)
                    {
                        objectFound = vm.Object[n];
                        break;
                    }
                }

                if (pi == null)
                {
                    throw new Exception(string.Format("Property {0} not found", propertyName));
                }

                value = pi.GetValue(objectFound, null);
            }
            else
            {
                value = pi.GetValue(o, null);
            }

            if (value == null)
            {
                var customAttribs = pi.ReadAttribute<ReturnValueWhenNullAttribute>();

                if (customAttribs != null && customAttribs.Length > 0)
                {
                    value = customAttribs[0].Val;
                }
            }

            return value;
        }

        public object DynamicSetValue(object o, string propertyName, object value)
        {
            MultiViewModelBase vm = o as MultiViewModelBase;
            Type t = o.GetType();
            PropertyInfo pi = t.GetProperty(propertyName);
            if (pi == null)
            {
                object objectFound = null;
                for (int n = 0; n < vm.Object.Count; n++)
                {
                    var obj = vm.Object[n];
                    if (obj == null)
                        continue;

                    t = obj.GetType();
                    pi = t.GetProperty(propertyName);

                    if (pi != null)
                    {
                        objectFound = vm.Object[n];
                        break;
                    }
                }

                if (pi == null)
                {
                    throw new Exception(string.Format("Property {0} not found", propertyName));
                }

                object val = Convert.ChangeType(value, pi.PropertyType, CultureInfo.InvariantCulture);
                pi.SetValue(objectFound, val, null);
            }
            else
            {
                object val = Convert.ChangeType(value, pi.PropertyType, CultureInfo.InvariantCulture);
                pi.SetValue(o, val, null);
            }

            return value;
        }
    }
}
